﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace eBook.Core
{
  internal class ISBNHyphenator
  {  
    // no validation logic here, item is assumed to be validated beforehand
         
    public string Hyphenate<T>(string isbnnum) where T:ISBN
    {
      return typeof(T) == typeof(ISBN10) ? HyphenateISBN10(isbnnum) : HyphenateISBN13(isbnnum);
    }
    
    public string HyphenateISBN10(string isbnnum)
    {
      return this.Hyphenate(isbnnum);
    }
    
    public string HyphenateISBN13(string isbnnum)
    {    
      string prefix = isbnnum.Substring(0,3) + "-";
	    string isbn   = isbnnum.Substring(3,10);

      return prefix + this.Hyphenate(isbn);
    }
    
    private string Hyphenate(string isbnnum)
    {
      int d  =  Convert.ToInt32( isbnnum.Substring(0,1) );	// one digit
      int d2 =  Convert.ToInt32( isbnnum.Substring(1,2) );	// two digits
      int d4 =  Convert.ToInt32( isbnnum.Substring(1,4) );	// four digits
      Regex objRegExp = null;
   
      switch(d) 
      {
        // 0 = English-speaking areas
        // 3 = German-speaking areas
        // 4 = Japan         
	      case 0:
        case 3:
        case 4: objRegExp = Region1Regex(d2);
                break;
        // 1 = English-speaking areas
	      case 1: objRegExp = Region2Regex(d4);
	              break;      
        // 2 = French-speaking areas      
        case 2: objRegExp = Region3Regex(d2);
	              break;             
        case 9:
          // 90 = Dutch/Flemish-speaking 
          if (isbnnum.Substring(1,2) == "0") 
          {
	          d2 = Convert.ToInt32( isbnnum.Substring(2,4) );
	          objRegExp = Region4Regex(d2);
          }      
          // 965 = Israel      
          if (isbnnum.Substring(1,3) == "65") 
          { 
	          d2 = Convert.ToInt32( isbnnum.Substring(3,5) );
	          objRegExp = Region5Regex(d2);
          }  
          // 981 = Singapore
          if (isbnnum.Substring(1,3) == "81") 
          {
	          d2 = Convert.ToInt32( isbnnum.Substring(3,5) );
	          objRegExp = Region6Regex(d2);
          }  

          break;

	      default:
   		      break;
      }


      return objRegExp != null ? objRegExp.Replace( isbnnum, "$1-$2-$3-$4" ) : isbnnum;
    }

    // 0 = English-speaking areas
    // 3 = German-speaking areas
    // 4 = Japan   
    protected Regex Region1Regex(int d2)
    {
      if (d2 < 20)
        return new Regex(@"(\d)(\d{2})(\d{6})(\w)");
      if (d2 < 70)
        return new Regex(@"(\d)(\d{3})(\d{5})(\w)");
      if (d2 < 85)
        return new Regex(@"(\d)(\d{4})(\d{4})(\w)");
      if (d2 < 90)
        return new Regex(@"(\d)(\d{5})(\d{3})(\w)");
      if (d2 < 95)
        return new Regex(@"(\d)(\d{6})(\d{2})(\w)");
      if (d2 <= 99)
        return new Regex(@"(\d)(\d{7})(\d)(\w)");
        
      return null;
    }

    // 1 = English-speaking areas    
    protected Regex Region2Regex(int d4)
    {    
      if (d4 < 1000)
        return new Regex(@"(\d)(\d{2})(\d{6})(\w)");
      if (d4 < 4000)
        return new Regex(@"(\d)(\d{3})(\d{5})(\w)");        
      if (d4 < 5500)
        return new Regex(@"(\d)(\d{4})(\d{4})(\w)");        
      if (d4 < 8698)
        return new Regex(@"(\d)(\d{5})(\d{3})(\w)");        
      if (d4 < 9990)
        return new Regex(@"(\d)(\d{6})(\d{2})(\w)");        
      if (d4 <= 9999)
        return new Regex(@"(\d)(\d{7})(\d)(\w)");

      return null;
    }    
    
    // 2 = French-speaking areas
    protected Regex Region3Regex(int d2)
    {
      if (d2 < 20)
        return new Regex(@"(\d)(\d{2})(\d{6})(\w)");

      if (d2 < 70)
        return new Regex(@"(\d)(\d{3})(\d{5})(\w)");

      if (d2 < 84)
        return new Regex(@"(\d)(\d{4})(\d{4})(\w)");

      if (d2 < 90)
        return new Regex(@"(\d)(\d{5})(\d{3})(\w)");

      if (d2 < 95)
        return new Regex(@"(\d)(\d{6})(\d{2})(\w)");

      if (d2 <= 99)
        return new Regex(@"(\d)(\d{7})(\d)(\w)");

      return null;      
    }
    
    // 90 = Dutch/Flemish-speaking   
    protected Regex Region4Regex(int d2)
    {
      if (d2 < 20)
        return new Regex(@"(\d{2})(\d{2})(\d{5})(\w)");
        
      if (d2 < 50)
        return new Regex(@"(\d{2})(\d{3})(\d{4})(\w)");
        
      if (d2 < 70)
        return new Regex(@"(\d{2})(\d{4})(\d{3})(\w)");
        
      if (d2 < 80)
        return new Regex(@"(\d{2})(\d{5})(\d{2})(\w)");
        
      if (d2 <= 81)
        return new Regex(@"(\d{2})(\d{6})(\d)(\w)");
       
      return null;      
    }
        
    // 965 = Israel
    protected Regex Region5Regex(int d2)
    {
      if (d2 < 20)
        return new Regex(@"(\d{3})(\d{2})(\d{4})(\w)");
        
      if (d2 < 70)
        return new Regex(@"(\d{3})(\d{3})(\d{3})(\w)");
        
      if (d2 < 90)
        return new Regex(@"(\d{3})(\d{4})(\d{2})(\w)");
        
      if (d2 <= 95)
        return new Regex(@"(\d{3})(\d{5})(\d)(\w)");
	          
      return null;      
    }    
    
    // 981 = Singapore
    protected Regex Region6Regex(int d2)
    {
      if (d2 < 20)
        return new Regex(@"(\d{3})(\d{2})(\d{4})(\w)");
        
      if (d2 < 30)
        return new Regex(@"(\d{3})(\d{3})(\d{3})(\w)");
        
      if (d2 <= 40)
        return new Regex(@"(\d{3})(\d{4})(\d{2})(\w)");

      return null;      
    }        
  
  
  }
}
